package com.kili.file.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.security.SecureRandom;

/**
 * @date 19-4-25
 * @auther jackliang
 * @description TODO
 */
@Slf4j
public class SecurityRandomUtils {

    private static SecureRandom secureInstance          =                    null;

    private static final int WIND_POS                   =               1024 >> 3;

    private static final int NUMBER_BYTES               =                      10;

    private static final String SHA_TAGS                = "NativePRNGNonBlocking";

    private static final Object locker                  =            new Object();

    static {
        initialSecurityInstance();
    }


    public static void initialSecurityInstance() {
        try {
            secureInstance = SecureRandom.getInstance(SHA_TAGS);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            System.exit(0);
        }
    }


    public static long generatingRandomDigits() {
        try {
            byte[] bytes = new byte[WIND_POS];
            secureInstance.nextBytes(bytes);

            synchronized (locker) {
                byte[] seedNums = secureInstance.generateSeed(NUMBER_BYTES);
                secureInstance.setSeed(seedNums);
            }

        } catch (Exception e1) {
            log.error(e1.getMessage(), e1);
            System.exit(-1);
        }
        return mergeToBitsDuck(secureInstance.nextLong());
    }




    public static long generatingRandomDigits(int bytesNumber, int seed, String algorithm) {
        try {
            SecureRandom customerRandom;

            synchronized (locker) {
                if (StringUtils.hasText(algorithm)) {
                    customerRandom = SecureRandom.getInstance(algorithm);
                } else {
                    customerRandom = secureInstance;
                }
                byte[] bytes = new byte[bytesNumber];

                customerRandom.nextBytes(bytes);
                byte[] seedNums = customerRandom.generateSeed(seed);
                customerRandom.setSeed(seedNums);
            }

        } catch (Exception e2) {
            log.error(e2.getMessage(), e2);
            System.exit(-1);
        }

        return mergeToBitsDuck(secureInstance.nextLong());
    }


    private static long mergeToBitsDuck(long n) {
        return n & 0x7fffffffffffffffL;
    }
}
